home *** CD-ROM | disk | FTP | other *** search
/ AMIGA-CD 2 / Amiga-CD - Volume 2.iso / ungepackte_daten / 1994 / 11 / 02 / tips.ampk / Tips & Tricks / ConvertCharSet / ConvertCharSet.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-01  |  14.6 KB  |  503 lines

  1. /*
  2.    ConvertCharSet   -- ein Programm zum Konvertieren von Zeichensätzen
  3.  
  4.       entstanden aus
  5.  
  6.    Arguments  -- eine CLI-Hülle für Programme ab Workbench 2.04
  7.  */
  8.  
  9. /*
  10.  *  allgemeine Include-Dateien
  11.  */
  12.  
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16.  
  17. /*
  18.  *  spezielle Amiga-Include-Dateien
  19.  */
  20.  
  21. #include <dos/dos.h>
  22. #include <dos/dosasl.h>
  23. #include <dos/rdargs.h>
  24. #include <exec/memory.h>
  25. #include <exec/types.h>
  26. #include <exec/execbase.h>
  27. #include <clib/exec_protos.h>
  28. #include <clib/dos_protos.h>
  29.  
  30. /*
  31.  * Defines, die bei einer Kopie zu ändern sind
  32.  */
  33.  
  34. #define PROGNAME "ConvertCharSet"     /* Default-Name des Programms     */
  35. #define VERSION  "1.5"                /* Versions-Nummer 1.0 am Anfang! */
  36. #define AUTHOR   "David Göhler"       /* Name des Autors                */
  37. #define DATE     "05.08.94"           /* Datum der letzten Änderung     */
  38. #define ENVVAR   PROGNAME             /* Name einer ENV-Variable        */
  39.  
  40. /*
  41.  * dauerhafte define's, die kaum einer Änderung bedürfen
  42.  */
  43.  
  44. #define NAMELEN  255                  /* Länge des Programmnamens       */
  45. #define LINELEN  10000                /* Zeilenlänge im Makefile        */
  46. #define BUFLEN   200                  /* Pufferlänge für Datei-Pattern  */
  47.  
  48. /*
  49.  * Flags für GetNextFileName
  50.  */
  51.  
  52. #define GNF_NODIR  1                  /* keine Verzeichnisse zurückgeben */
  53. #define GNF_ALL    2                  /* auch Unterverzeichnisse */
  54.  
  55. /*
  56.  * spezielle Defines nur für dieses Programm
  57.  */
  58.  
  59. #define LF         0x0A               /* linefeed */
  60. #define CR         0x0D               /* Carriage Return */
  61.  
  62. #define TABLETEMPLATE    "s:%s.tab"
  63.  
  64. /*
  65.  * falls ein GCC zum Einsatz kommt, DICE-Spezialitäten abwürgen
  66.  */
  67.  
  68. #ifdef __GNUC__
  69. #define __stkargs                     /* kennt der GCC nicht            */
  70. #endif
  71.  
  72. const char VersionID      []="$VER: " PROGNAME " " VERSION " - © " AUTHOR " (" DATE ")";
  73. const char TemplateString []="FILES/A/M,TABLE/A,EXT=EXTENSION/K,DEST=DESTINATION/K,STRIPLF/S,STRIPCR/S,LF2CR/S,CR2LF/S,QUIET/S,NOENV/S";
  74. enum       TemplateEnum     { FILES,TABLE,EXTENSION,DESTINATION,STRIPLF,STRIPCR,LF2CR,CR2LF,QUIET,NOENV };
  75.  
  76. BOOL    somethingfound = FALSE;
  77.  
  78. typedef struct {
  79.         char *filenames;      /* Datei oder Pattern der umzuwandelnden Dateien */
  80.         char *table;          /* Convertierungstabelle */
  81.         char *extension;      /* Extension, die anzuhängen ist */
  82.         char *destination;    /* Zielname, falls gewünscht */
  83.         LONG striplf;
  84.         LONG stripcr;
  85.         LONG lf2cr;
  86.         LONG cr2lf;
  87.         LONG quiet;           /* keine Ausgaben, wenn TRUE */
  88.         LONG noenv;           /* ENV-Variable nicht auswerten wenn TRUE */
  89. } Template;                   /* Für die Kommandozeile */
  90.  
  91. /*
  92.  * globale Variablen, die die Einstellungen per Kommandozeile darstellen
  93.  */
  94.  
  95. char  EnvString [BUFLEN] = "";        /* für eine eventuelle Env-Variable */
  96. char  progname  [NAMELEN]= PROGNAME;  /* Für Ausgaben bei Fehlermeldungen */
  97. char  infile    [NAMELEN]= "";        /* Dateiname des Files zum Lesen    */
  98. char  inext     [50]     = "";        /* Extension der in-Datei           */
  99. char  outfile   [NAMELEN]= "";        /* Dateiname des Files zum Schreiben*/
  100. char  outext    [50]     = "";        /* Extension für out-Datei          */
  101.  
  102. Template CommandLineVars = {          /* Template-Struktur für ReadArgs   */
  103.      0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L
  104. };
  105.  
  106. unsigned char tt[256];                /* Translate table space*/
  107.  
  108. char    TempBuf[BUFLEN];
  109. struct  RDArgs  EnvArgs   = {
  110.         {  EnvString, BUFLEN, 0 },
  111.         0, TempBuf, BUFLEN,
  112.         0L,           // Extra Help Text, currently zero
  113.         RDAF_NOALLOC | RDAF_NOPROMPT
  114. };
  115.  
  116. /*
  117.  * externe Referenzen
  118.  */
  119.  
  120. extern struct ExecBase *SysBase;   /* Für den Versionstest */
  121.  
  122. /*
  123.  * Funktionen, die im folgenden erst Definiert werden
  124.  */
  125.  
  126. char *GetNextFileName(Template *, LONG);
  127. void initchars(char *TABLENAME, long lf2cr, long cr2lf, long quiet);
  128. BOOL ConvertFile(char *SrcName,char *DestName,long striplf, long stripcr);
  129. char *GetFileName(char *FileName,BOOL extension);
  130.  
  131. /*
  132.  * main-Kopf, für GCC-Nutzer mit Extrawurst
  133.  */
  134.  
  135. //__stkargs void _main()          /* hier beginnt das Programm */
  136. int main(int argc, char *argv[])
  137. {
  138.    struct RDArgs *rda;              /* nicht notwendigerweise global */
  139.    long           rc  = RETURN_OK;  /* Return-Code von main          */
  140.  
  141.    /* dies Programm läuft nur ab Version 2.04 */
  142.    if (SysBase->LibNode.lib_Version < 37)
  143.    {  Write(Output(),"Wrong kickstart version, must 37.175 or higher\n",47);
  144.       _exit(RETURN_FAIL);
  145.    }
  146.  
  147.    /* wie heiße ich denn ? */
  148.    if (!GetProgramName(progname,NAMELEN-1))   /* bei Fehlversuch */
  149.    {  strncpy(progname,PROGNAME,NAMELEN-1); } /* Default kopieren */
  150.  
  151.  
  152.    if (CommandLineVars.noenv == FALSE)
  153.    {  // vor der KommandoZeile die ENV-Variable aus ENVVAR auswerten
  154.       if (GetVar(ENVVAR,EnvString,BUFLEN,0) > 0)
  155.       {  // muß sein, möglicherweise ein Bug in ReadArgs
  156.          strcat(EnvString," "); // kennt jemand dieses Problem ?
  157.  
  158.          EnvArgs.RDA_Source.CS_Length = strlen(EnvString);
  159.          if (rda = ReadArgs(TemplateString,(LONG *) &CommandLineVars,&EnvArgs))
  160.          {  FreeArgs(rda); }
  161.       }
  162.    }
  163.  
  164.    /* nun die Kommandozeilenauswertung erledigen - per Systemaufruf */
  165.    if (rda = ReadArgs (TemplateString,(LONG *) &CommandLineVars,NULL))
  166.    {
  167.       char *FileName = 0L;           /* Zeigt auf einen Dateinamen */
  168.       char tablename[50] = "";
  169.  
  170.       /*
  171.        * Zuerst den Tabellennamen herausfinden.
  172.        */
  173.       
  174.       sprintf(tablename,TABLETEMPLATE,CommandLineVars.table);
  175.       initchars(tablename,CommandLineVars.lf2cr,
  176.                           CommandLineVars.cr2lf,
  177.                           CommandLineVars.quiet);
  178.  
  179.       /* CommandLineVars.filenames zeigt auf ein Array von StrPrtn */
  180.       /* Diese werden mit einem NULL-Pointer abgeschlossen         */
  181.       /* statt diese nun per Hand auszuwerten, rufe ich mit dem    */
  182.       /* Zeiger auf CommandLineVars eine Funktion auf, die jeweils */
  183.       /* bei einem Aufruf einen Zeiger auf einen String=Dateiname  */
  184.       /* oder NULL zurückliefert. Im NULL-Fall ist per IoErr()     */
  185.       /* auf einen Fehler zu prüfen.                               */
  186.  
  187.  
  188.       while (FileName = GetNextFileName(&CommandLineVars,GNF_NODIR))
  189.       {
  190.         char *pos = 0L;
  191.         
  192.         somethingfound = TRUE;
  193.  
  194.         if (CommandLineVars.extension != 0L)
  195.         {  
  196.            if (*CommandLineVars.extension == '.')
  197.            {  strcpy(outext,CommandLineVars.extension); 
  198.            }
  199.            else
  200.            {  strcpy(outext,".");
  201.               strcat(outext,CommandLineVars.extension);
  202.            }
  203.         }
  204.         else
  205.         {  if (pos = strrchr(CommandLineVars.table,'2'))
  206.            {  *pos = '.';
  207.               strcpy(outext,pos);
  208.               *pos = '2';
  209.            }
  210.            else
  211.            {  strcpy(outext,".conv"); }
  212.         }
  213.  
  214.         if (CommandLineVars.destination != 0L)
  215.         {  char *pos2;
  216.            if (pos2 = strstr(pos=CommandLineVars.destination,"#?"))
  217.            {
  218.               strncpy(pos2,"%s",2);
  219.               sprintf(outfile,pos,GetFileName(FileName,FALSE));
  220.               strncpy(pos2,"#?",2);
  221.            }
  222.            else
  223.            {  strcpy(outfile,CommandLineVars.destination);
  224.            }
  225.         }
  226.         else
  227.         {
  228.            if (pos = strrchr(FileName,'.'))
  229.            {  *pos = 0;
  230.               strcpy(outfile,FileName);
  231.               *pos = '.';
  232.               strcat(outfile,outext);
  233.            }
  234.            else
  235.            {  strcpy(outfile,FileName);
  236.               strcat(outfile,outext);
  237.            }
  238.         }
  239.  
  240.         if (!CommandLineVars.quiet)
  241.         {  printf("Converting '%s' to '%s' using '%s' ...",
  242.                    FileName,outfile,tablename);
  243.            fflush(stdout);
  244.         }
  245.         if (ConvertFile(FileName,outfile,
  246.                         CommandLineVars.striplf,
  247.                         CommandLineVars.stripcr))
  248.         {  if (!CommandLineVars.quiet)  puts("O.K."); }
  249.         else
  250.         {  if (!CommandLineVars.quiet)  puts("not O.K."); }
  251.       }
  252.  
  253.       /* Wenn nicht alle Einträge gelesen wurde, liegt ein Fehler vor */
  254.       if (IoErr() != ERROR_NO_MORE_ENTRIES)
  255.       {  rc = RETURN_FAIL; }
  256.  
  257.       /* alloziertes wieder freigeben */
  258.       FreeArgs(rda);
  259.    }
  260.    else
  261.    {  rc = RETURN_ERROR; }
  262.  
  263.    /* bei einem Fehler, den Fehler ausgeben */
  264.    if (rc != RETURN_OK) PrintFault(IoErr(),progname);
  265.  
  266.    if ((rc == RETURN_OK) && (somethingfound == FALSE))
  267.    {  rc = RETURN_WARN; }
  268.  
  269.    return rc;
  270. }
  271.  
  272. BOOL IsFile(struct FileInfoBlock *fib)
  273. {
  274.    return ((fib->fib_DirEntryType == ST_FILE) ||
  275.        (fib->fib_DirEntryType == ST_LINKFILE) ||
  276.        (fib->fib_DirEntryType == ST_SOFTLINK));
  277. }
  278.  
  279. /*
  280.  * für eine Funktionsbeschreibung s.o.
  281.  *
  282.  * all noch nicht implementiert 25. Oktober 1992
  283.  */
  284.  
  285. char *GetNextFileName(Template *CLV, LONG flags)
  286. {
  287.    /* für den Vergleich, ob ich zum ersten Mal aufgerufen wurde */
  288.    static Template lastcallCLV = {0,0,0};
  289.    static char **arraypointer = 0;   /* zeigt auf das aktuelle Pattern */
  290.    static struct AnchorPath *AP = 0; /* Struktur für Match-Funktionen  */
  291.    static BOOL FirstTimeThisName = FALSE;
  292.    int    retcode = NULL;
  293.  
  294.    if (lastcallCLV != *CLV)  /* erster Aufruf, alles richten */
  295.    {  arraypointer = CLV->filenames;  /* Zeigt auf das erste Pattern */
  296.       FirstTimeThisName = TRUE;       /* Dieses Pattern zum ersten Mal */
  297.       lastcallCLV = *CLV;             /* jetzt gleich ! */
  298.       if (AP != NULL)                 /* zeigt noch auf was ??? */
  299.       {  FreeMem(AP,sizeof(*AP)+NAMELEN); AP = NULL; }
  300.  
  301.       /* nun erst einmal die nötige Struktur allozieren */
  302.       if (!(AP = AllocMem(sizeof(*AP)+NAMELEN,MEMF_PUBLIC | MEMF_CLEAR)))
  303.       {
  304.          SetIoErr(ERROR_NO_FREE_STORE);
  305.          return NULL;
  306.       }
  307.  
  308.       /* das System soll mir gefälligst die vollen Namen liefern */
  309.       AP->ap_Strlen    = NAMELEN;
  310.  
  311.       /* und auf CTRL-C soll es auch selbst aufpassen */
  312.       AP->ap_BreakBits = SIGBREAKF_CTRL_C;
  313.    }
  314.  
  315.    while (*arraypointer != NULL) /* noch ein Pattern da */
  316.    {
  317.       if (FirstTimeThisName)  /* dann MatchFirst benutzen */
  318.       {
  319.          FirstTimeThisName = FALSE;
  320.          if (!(retcode = MatchFirst(*arraypointer,AP))) /* 0 = Is OK!!!!! */
  321.          {  if (flags & GNF_NODIR)
  322.             {  if (!IsFile(&(AP->ap_Info)))
  323.                {  continue; }
  324.             }
  325.             return AP->ap_Buf;
  326.          }
  327.          else
  328.          {  SetIoErr(retcode);
  329.             MatchEnd(AP);                          /* ob das sein muß ?? */
  330.             FreeMem(AP,sizeof(*AP)+NAMELEN); AP = NULL;
  331.             return NULL;
  332.          }
  333.       }
  334.       else
  335.       {
  336.          if (!(retcode = MatchNext(AP))) /* 0 = Is OK!!!!! */
  337.          {  if (flags & GNF_NODIR)
  338.             {  if (!IsFile(&(AP->ap_Info)))
  339.                {  continue; }
  340.             }
  341.             return AP->ap_Buf;
  342.          }
  343.          else
  344.          {  if (retcode == ERROR_NO_MORE_ENTRIES) /* nächstes Pattern */
  345.             {  arraypointer ++;
  346.                MatchEnd(AP); /* AP so lassen, hat ja gepaßt */
  347.                FirstTimeThisName = TRUE;
  348.             }
  349.             else
  350.             {  SetIoErr(retcode);
  351.                MatchEnd(AP); /* ob das hier sein muß ? */
  352.                FreeMem(AP,sizeof(*AP)+NAMELEN); AP = NULL;
  353.                return NULL;
  354.             }
  355.          }
  356.       }
  357.    }
  358.  
  359.    if (AP != NULL)                 /* zeigt noch auf was ??? */
  360.    {  FreeMem(AP,sizeof(*AP)+NAMELEN); AP = NULL; }
  361.  
  362.    SetIoErr(ERROR_NO_MORE_ENTRIES);
  363.    return NULL;
  364. }
  365.  
  366.  
  367. void initchars(char *TABLENAME, long lf2cr, long cr2lf, long quiet)
  368. {
  369.    int i;
  370.    FILE *in;
  371.    BOOL ok = FALSE;
  372.  
  373.    for (i=0; i < 256; i++)
  374.    {  tt[i] = i; }
  375.  
  376.    if (in = fopen(TABLENAME,"rb"))
  377.    {  if (fread(tt,256,1,in) > 0)
  378.       {  ok = TRUE; }
  379.       else
  380.       {  if (!quiet) 
  381.          {  printf("Read from '%s' failed\n",TABLENAME);
  382.          }
  383.       }
  384.  
  385.       fclose(in);
  386.    }
  387.    else
  388.    {  if (!quiet)
  389.       {  printf("Conversion table '%s' not found - use builtin \"Mac to Amiga\"\n",
  390.               TABLENAME);
  391.       }
  392.    }
  393.  
  394.  
  395.    if (! ok)
  396.    {
  397.       tt['ä'] = 0x8a;
  398.       tt['ö'] = 0x9a;
  399.       tt['ü'] = 0x9f;
  400.       tt['ß'] = 167;
  401.       tt['Ä'] = 0x80;
  402.       tt['Ö'] = 0x85;
  403.       tt['Ü'] = 0x86;
  404.       tt['»'] = 200;
  405.       tt['«'] = 199;
  406.       tt['é'] = 0x8e;
  407.    }
  408.  
  409.    if (lf2cr)  tt[LF]  = CR;
  410.    if (cr2lf)  tt[CR]  = LF;
  411. }
  412.  
  413. BOOL ConvertFile(char *SrcName,char *DestName, 
  414.                  long striplf, long stripcr)
  415. {
  416.    FILE *in,*out;
  417.    BOOL retcode = FALSE;
  418.  
  419.    if (in = fopen(SrcName,"rb"))
  420.    {
  421.       if (out = fopen(DestName,"wb"))
  422.       {
  423.          register int inchar;
  424.          while ((inchar = fgetc(in)) != EOF)
  425.          {
  426.             switch (inchar) {
  427.                case LF: if (striplf)
  428.                         {  if ((inchar = fgetc(in)) != EOF)
  429.                            {  if (inchar == LF)
  430.                               {  fputc(tt[LF],out); } // doppeltes Linefeed
  431.                               else
  432.                               {  fputc(' ',out);     // Space
  433.                                  fputc(tt[inchar],out); // und den Buchstaben
  434.                               }
  435.                            }
  436.                            else
  437.                            {  fputc(tt[LF],out); } // war letzter Buchstabe
  438.                         }
  439.                         else
  440.                         {  fputc(tt[LF],out); }
  441.                         break;
  442.                case CR: if (stripcr)
  443.                         {  if ((inchar = fgetc(in)) != EOF)
  444.                            {  if (inchar == CR)
  445.                               {  fputc(tt[CR],out); } // doppeltes Linefeed
  446.                               else
  447.                               {  fputc(' ',out);     // Space
  448.                                  fputc(tt[inchar],out); // und den Buchstaben
  449.                               }
  450.                            }
  451.                            else
  452.                            {  fputc(tt[CR],out); } // war letzter Buchstabe
  453.                         }
  454.                         else
  455.                         {  fputc(tt[CR],out); }
  456.                         break;
  457.                default: fputc(tt[inchar],out);
  458.                         break;
  459.             }
  460.          }
  461.          retcode = TRUE;
  462.          fclose(out);
  463.       }
  464.       else
  465.       {  printf("Konnte %s nicht zum Schreiben nicht öffnen\n",DestName);
  466.       }
  467.       fclose(in);
  468.    }
  469.    else
  470.    {  printf("Konnte %s nicht zum Lesen nicht öffnen\n",SrcName);
  471.    }
  472.  
  473.    return retcode;
  474. }
  475.  
  476. char *GetFileName(char *FileName,BOOL extension)
  477. {
  478.    static char buf[100];
  479.    char *pos = 0;
  480.    char *ext = 0;
  481.  
  482.    if ((pos = strrchr(FileName,'/')) == 0)
  483.    {  if ((pos = strrchr(FileName,':')) == 0)
  484.       {  pos = FileName; }
  485.       else
  486.       {  pos++; }
  487.    }
  488.    else
  489.    {  pos++; }
  490.  
  491.    if (!extension)
  492.    {  if (ext = strrchr(FileName,'.'))
  493.       {  *ext = '\0'; }
  494.    }
  495.  
  496.    strncpy(buf,pos,100);
  497.  
  498.    if (ext != 0L)
  499.    {  *ext = '.'; }
  500.  
  501.    return buf;
  502. }
  503.